﻿using ATC8225_Driver;
using OptoskyConnector;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Om.Camera.ATH1010_25;

public class AthCamera : IBaseCamera
{
    ATC8225 driver = new ATC8225();
    private Bitmap _currentBitmap;

    public AthCamera()
    {
        
        ATC8225.OriginalDataBuffer += ATC8225_OriginalDataBuffer;
    }

    private void ATC8225_OriginalDataBuffer(IEnumerable<byte> originalData)
    {
        byte[] resdata = GammaExcute(originalData, 0.1);
        _currentBitmap = CreateGrayImage(resdata, 640, 512);

        using var ms = new MemoryStream();
        // 将 Bitmap 对象保存到 MemoryStream 中，指定图片格式
        _currentBitmap.Save(ms, ImageFormat.Jpeg);
        // 将 MemoryStream 中的数据转换为 byte[]
        FrameReceived?.Invoke(ms.ToArray());

    }

    private bool _isConnected;
    public bool IsConnected
    {
        get => _isConnected;
        private set
        {
            if (_isConnected != value)
            {
                _isConnected = value;
                ConnectionChanged?.Invoke(this, value);
            }
        }
    }
    public event Action<byte[]>? FrameReceived;
    public event EventHandler<bool>? ConnectionChanged;
    public string Id { get; private set; }
    public async Task<List<string>> GetCameraList()
    {
        var res = CyUsbConnector.Devices;
        return res.ToList();
    }

    public async Task Connect(string cameraIpOrName)
    {
        driver.ConnectByCyUSB(cameraIpOrName);

        Id = cameraIpOrName;
        IsConnected = true;

        driver.GetOriginalData(0);
    }

    public async Task Disconnect()
    {
        driver.StopGetData();
        driver.DisConnect();
        IsConnected = false;
    }

    public async Task Capture(string fileName)
    {
        try
        {
            _currentBitmap.Save(fileName);
        }
        catch (Exception ex) { 
        }
    }

    public bool CanSetExposure => false;
    public async Task<bool> SetAutoExposure(bool isAutoExposure)
    {
        return false;
    }

    public async Task<bool> SetExposureValue(int val)
    {
        return false;
    }

    public async Task<int> GetExposureValue()
    {
        return 0;
    }

    #region method

    /// <summary>
    /// 数据伽马值处理
    /// </summary>
    /// <param name="bytes"></param>
    /// <param name="gamma"></param>
    /// <returns></returns>
    private byte[] GammaExcute(IEnumerable<byte> bytes, double gamma = 0.4, string bit = "14")
    {
        var IsReverse = true;
        var data = bytes.ToArray();
        var result = new List<byte>();

        if (bit == "12")
        {
            //// 原始的_   最老版本 （12位）
            for (int i = 0; i < data.Length - 1; i += 2)
            {
                // 取12位    
                var x = ((data[i] << 8) + data[i + 1]) & 0xFFF;
                var val = IsReverse ? 255 - 256 * Math.Pow(x / 4095.0, gamma) : 256 * Math.Pow(x / 4095.0, gamma);
                result.Add((byte)val);

                // result.Add((byte)Clamp(val, 0, 255)); // 确保 val 在 0 到 255 之间
            }
        }
        else
        {
            //20241016 14位
            for (int i = 0; i < data.Length - 1; i += 2)
            {
                // 取12位
                var x = ((data[i] << 8) + data[i + 1]) & 0x3FFF;
                var val = IsReverse ? 255 - 256 * Math.Pow(x / 16383.0, gamma) : 256 * Math.Pow(x / 16383.0, gamma);
                //result.Add((byte)val);

                result.Add((byte)Clamp(val, 0, 255)); // 确保 val 在 0 到 255 之间
            }
        }

        return result.ToArray();
    }

    private double Clamp(double value, double min, double max)
    {
        if (value < min) return min;
        if (value > max) return max;
        return value;
    }
    /// <summary>
    /// 数据转换成灰度图
    /// </summary>
    /// <param name="byteArray"></param>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <returns></returns>
    private Bitmap CreateGrayImage(byte[] byteArray, int width, int height)
    {
        // 创建灰度图像
        var grayImage = new Bitmap(width, height, PixelFormat.Format8bppIndexed);

        // 设置调色板为灰度
        ColorPalette palette = grayImage.Palette;
        for (int i = 0; i < 256; i++)
        {
            palette.Entries[i] = Color.FromArgb(i, i, i);
        }
        grayImage.Palette = palette;

        // 将 byte 数组写入图像的像素
        BitmapData bmpData = grayImage.LockBits(new Rectangle(0, 0, width, height),
            ImageLockMode.WriteOnly,
            grayImage.PixelFormat);
        int stride = bmpData.Stride;
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int index = y * stride + x;
                if (index < byteArray.Length)
                {
                    Marshal.WriteByte(bmpData.Scan0, index, byteArray[index]);
                }
            }
        }

        grayImage.UnlockBits(bmpData);

        return grayImage;
    }


    #endregion
}